package com.waves.task.strategy.task;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.waves.core.constant.redis.TaskRedisKey;
import com.waves.core.utils.*;
import com.waves.task.dao.TaskCommentDao;
import com.waves.task.dao.TaskDao;
import com.waves.task.domain.dto.TaskPageDTO;
import com.waves.task.domain.entity.Task;
import com.waves.task.domain.enums.TaskTypeEnum;
import com.waves.task.domain.vo.TaskVO;
import com.waves.task.service.impl.TaskServiceImpl;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * Description: 消息标记抽象类
 * Author: dlw
 * Date: 2023-05-30
 */
public abstract class AbstractTaskStrategy {

    @Resource
    protected TaskDao taskDao;

    @Resource
    protected TaskCommentDao taskCommentDao;

    @PostConstruct
    private void init() {
        TaskFactory.register(getTaskTypeEnum().getType(), this);
    }

    abstract TaskTypeEnum getTaskTypeEnum();

    /**
     * 处理查询请求参数
     *
     * @param dto 分页请求参数
     * @return 处理好的请求参数
     */
    abstract TaskPageDTO dealTaskPageDTO(TaskPageDTO dto);

    /**
     * 获取查询返回数据
     *
     * @param dto 分页请求参数
     * @return 分页查询结果
     */
    public abstract IPage<TaskVO> getTaskVOPage(TaskPageDTO dto);

    /**
     * 分页查询数据公共方法
     *
     * @param dto 分页请求参数
     * @return 分页查询结果并处理结果
     */
    protected IPage<TaskVO> searchAndDealPage(TaskPageDTO dto) {
        Long userId = LoginUtils.getUserId();
        // 分页查询
        Page<Task> taskPage = taskDao.listTaskPage(dto);
        // 数据处理
        IPage<TaskVO> taskVOS = taskPage.convert(t -> {
            TaskVO taskVo = BeanUtil.copyProperties(t, TaskVO.class);
            // 设置发帖人距离
            if (CollUtil.isNotEmpty(dto.getDistanceMap())) {
                taskVo.setDistance(dto.getDistanceMap().get(taskVo.getUserId()));
            }
            if (StringUtils.isNotEmpty(t.getImgUrl())) {
                taskVo.setImages(Arrays.asList(t.getImgUrl().split(";")));
            }
            // 描述和内容两者只会存一
            if (StringUtils.isEmpty(t.getDescription())) {
                String content = replaceImg(t.getContent());
                if (StringUtils.isNotEmpty(content)) {
                    taskVo.setDescription(content.substring(0, Math.min(content.length(), 30)));
                }
            }
            // 将图片地址截取
            if (StringUtils.isNotEmpty(t.getContent())) {
                taskVo.setContent(replaceImg(t.getContent()));
            }
            return taskVo;
        });
        // 多线程异步 设置当前用户是否点赞、收藏与关注
        List<CompletableFuture<Void>> completableFutureList = new ArrayList<>();
        for (TaskVO t : taskVOS.getRecords()) {
            completableFutureList.add(CompletableFutureUtils.createRun(() ->
                    TaskServiceImpl.setLikedAndCollectedTask(t, userId)));
        }
        CompletableFuture.allOf(completableFutureList.toArray(CompletableFuture[]::new)).join();
        return taskVOS;
    }

    /**
     * 内容将图片地址替换
     * @param content
     * @return
     */
    protected String replaceImg(String content) {
        int startIndex = content.indexOf("![]");
        if (startIndex != -1) {
            int endIndex = content.contains("jpg") ? content.indexOf("jpg") : content.indexOf("png");
            String replaceStr = content.substring(startIndex, endIndex + 4);
            String str = content.replace(replaceStr, "");
            return replaceImg(str);
        } else {
            return content;
        }
    }

    /**
     * 判断这条帖子当前用户是否收藏
     *
     * @param id     帖子id
     * @param userId 当前用户
     */
    protected boolean isCollected(Long id, Long userId) {
        String collectedKey = TaskRedisKey.getKey(TaskRedisKey.TASK_COLLECTED_SET, id);
        if (Objects.nonNull(userId)) {
            return RedisUtils.sIsMember(collectedKey, userId);
        }
        return false;
    }
}
